package fr.auzaiphe.joueur.model;

import java.util.ArrayList;

import javax.swing.JOptionPane;

import fr.auzaiphe.commun.Model;
import fr.auzaiphe.commun.reseau.PacketBuyIndice;
import fr.auzaiphe.commun.reseau.PacketSayDeconnexion;
import fr.auzaiphe.commun.reseau.ReseauClient;
import fr.auzaiphe.joueur.view.JoueurView;

/**
 * @author Jojo
 * @author Hugp
 */
public class JoueurModel extends Model
{
	private boolean partieLancee;
	private ReseauClient client;

	private ArrayList<String[]> listeJoueurs;
	private ChronoGeneralJoueur chronoPartie;
	private boolean estConnecte;
	private int prixIndice;

	private JoueurConnecte joueurConnecte;

	public JoueurModel( ReseauClient pClientChat )
	{
		this.partieLancee = false;
		this.estConnecte = false;
		this.client = pClientChat;
		this.listeJoueurs = new ArrayList<String[]>();
		this.chronoPartie = new ChronoGeneralJoueur( this );
		this.prixIndice = 0;

		this.setChanged();
		this.notifyObservers();
	}

	/**
	 * Appeler par le PacketInitDataParty
	 * Permet de faire le premier set de la liste des joueurs et
	 * du chrono g�n�ral de la partie
	 * @param tempsChrono
	 * @param listeJoueurs
	 */
	public void setOptionsPartie(boolean pOn, int tempsChrono, ArrayList<String[]> listeJoueurs, int pPrix)
	{
		this.chronoPartie.setTempsRestant( tempsChrono );
		this.listeJoueurs.clear();
		this.listeJoueurs.addAll( listeJoueurs );

		this.prixIndice = pPrix;

		if(pOn)
		{
			this.lancerPartie();
		}

		this.setChanged();
		this.notifyObservers();
	}

	/**
	 * Appeller par le paquet PacketStartParty
	 * Permet de lancer la partie lorsque l'application admin le demande.
	 * Demarre le chrono général.
	 */
	public void lancerPartie()
	{
		this.partieLancee = true;
		this.chronoPartie.start();
	}

	/**
	 * Appeller par le PacketStopParty
	 * Pemret de stopper la partie lorsque l'application admin le demande
	 * Stop le chrono général
	 */
	public void stopperPartie()
	{
		this.partieLancee = false;
		this.chronoPartie.interrupt();
		if ( this.estConnecte )
		{
			this.deconnecter();
		}
	}

	/**
	 * Appeller par le PacketUpdateChronoGeneral
	 * Envoyer lorsque l'admin modifie le chrono manuellement
	 * @param pTempsRestant
	 */
	public void updateTempsRestant(int pTempsRestant)
	{
		this.chronoPartie.setTempsRestant(pTempsRestant);

		this.setChanged();
		this.notifyObservers();
	}

	public void connecter( int pTempsRestant, String pNom, String pPrenom, String pPassword, ArrayList<IndiceJoueur> indicesDispos )
	{
		this.estConnecte = true;
		this.joueurConnecte = new JoueurConnecte( this,
												  pTempsRestant,
												  pNom,
												  pPrenom,
												  pPassword,
												  indicesDispos );
		this.client.setPseudo( pNom + " " + pPrenom );

		this.setChanged();
		this.notifyObservers( JoueurView.REFRESH_ALL );
	}

	/**
	 * Deconnexion :
	 * Vide les infos joueur connecte, met en deconnecté, envoie à l'admin les infos du joueur.
	 */
	public void deconnecter ()
	{
		this.estConnecte = false;

		this.getClient().send(new PacketSayDeconnexion(this.getJoueurConnecte().getNom(), this.getJoueurConnecte().getPassword(), this.getJoueurConnecte().getChronoJoueurConnecte().getSecondesRestantes()));
		this.client.setPseudo("Joueur");
		this.joueurConnecte.supprimerTousIndices();
		this.joueurConnecte = null;

		this.setChanged();
		this.notifyObservers( JoueurView.REFRESH_ALL );
	}

	public void setChronoJoueur(int pTemps, String pNom, String pPassword)
	{
		if(this.joueurConnecte != null)
		{
			System.out.println( this.joueurConnecte.getNom() + " == " + pNom );
			System.out.println( this.joueurConnecte.getPassword() + " == " + pPassword );
			if(this.joueurConnecte.getNom().equals(pNom) && this.joueurConnecte.getPassword().equals(pPassword))
			{
				System.out.println("TEST PASSAGE");
				this.joueurConnecte.getChronoJoueurConnecte().setTempsRestant(pTemps);
				this.setChanged();
				this.notifyObservers();
			}
		}
	}

	/**
	 * Reset la liste des indices du joueur durant sa connexion.
	 * Se produit lorsque le joueur est connecté et que l'admin
	 * modifie ses indices
	 * @param pNouvelleListe
	 */
	public void resetListeIndiceJoueurCo(ArrayList<IndiceJoueur> pNouvelleListe)
	{
		this.joueurConnecte.setListeIndiceJoueurConnecte( pNouvelleListe );

		this.setChanged();
		this.notifyObservers( JoueurView.REFRESH_INDICE );
	}

	public void buyIndice()
	{
		if(this.joueurConnecte.getChronoJoueurConnecte().getSecondesRestantes() > this.prixIndice)
			this.getClient().send(new PacketBuyIndice(this.joueurConnecte.getNom(),this.joueurConnecte.getPassword()));
		else
			JOptionPane.showMessageDialog(null, "Vous n'avez plus assez de temps", "Erreur", JOptionPane.ERROR_MESSAGE);
	}

	/**
	 * Informe la vue qu'elle doit se mettre à jour
	 * Essentiellement utile pour les Chronos
	 */
	@Override
	public void updateVue()
	{
		this.setChanged();
		this.notifyObservers();
	}

	public void putError(String text)
	{
		JOptionPane.showMessageDialog(null, text, "Erreur joueur", JOptionPane.ERROR_MESSAGE);
	}

	public JoueurConnecte getJoueurConnecte()
	{
		return this.joueurConnecte;
	}

	public ReseauClient getClient()
	{
		return this.client;
	}

	public boolean isConnected()
	{
		return this.estConnecte;
	}

	/**
	 * @return the chronoPartie
	 */
	public ChronoGeneralJoueur getChronoPartie()
	{
		return this.chronoPartie;
	}

	public int getPrix()
	{
		return this.prixIndice;
	}

	public void setPrix(int pPrix)
	{
		this.prixIndice = pPrix;

		this.setChanged();
		this.notifyObservers();
	}

	/**
	 * @return the partieLancee
	 */
	public boolean isPartieLancee()
	{
		return this.partieLancee;
	}

	/**
	 * @param listeJoueurs the listeJoueurs to set
	 */
	public void setListeJoueurs(ArrayList<String[]> listeJoueurs)
	{
		this.listeJoueurs = listeJoueurs;

		this.setChanged();
		this.notifyObservers( JoueurView.REFRESH_JOUEUR );
	}

	/**
	 * @return the listeJoueurs
	 */
	public ArrayList<String[]> getListeJoueurs()
	{
		return this.listeJoueurs;
	}
}
